const path = require("path");//nodejs核心模块，专门用来处理路径问题
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const { VueLoaderPlugin } = require('vue-loader');
const { DefinePlugin } = require("webpack")
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
// 第三方组件库按需导入
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

const isProduction = process.env.NODE_ENV === 'production' ? true : false


function getStyleLoaders(pre) {
  return [
    isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader',
    'css-loader', //将css资源编译成commonjs的模块到js中
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: [
            [
              'postcss-preset-env',
            ],
          ],
        },
      },
    },
    pre && {
      loader: pre,
      options: 
      pre === "sass-loader"
      ? {
        additionalData: `@use "@/styles/element/index.scss" as *;`,
      }:{}
    }
  ].filter(Boolean) //array.filter(Boolean)：过滤假数据（false,0,-0."",null,undefined,NaN）
}


module.exports = {
  // 入口
  entry: "./src/main.js",
  // 输出
  output: {
    // 文件的输出路径
    path: isProduction ? path.resolve(__dirname, "../dist") : undefined,
    // 文件名
    filename: isProduction ? "static/js/[name].[contenthash:10].js" : "static/js/[name].js",
    // 动态导入输出资源命名方式
    chunkFilename: isProduction ? "static/js/[name].chunk.[contenthash:10].js" : "static/js/[name].chunk.js",//chunk区分于主文件
    // 图片、字体等资源命名方式
    assetModuleFilename: isProduction ? 'static/media/[contenthash:10][ext]' : 'static/media/[ext]',
    // 自动清空上次打包的内容
    clean: true,
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        test: /\.css$/, //只检测.css文件
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/, //只检测.less文件
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/, //只检测.less文件
        use: getStyleLoaders("sass-loader"),
      },
      // 将小于6kb的图片转为data URL(base64编码)，大于的不转，减少连接
      // 默认8kb，通过parser.dataUrlCondition.maxSize自定义
      {
        test: /\.(png|jpe?g|gif|webp|svg)$/,
        type: 'asset',
        parser: {
          // 将小于4kb的文件转化为base64的url
          dataUrlCondition: {
            maxSize: 6 * 1024 // 6kb
          }
        },
      },
      // 配置目的：将文件统一存储，配合output.assetModuleFilename
      {
        test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
        type: 'asset/resource',
      },
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true, // 开启babel编译缓存
              cacheCompression: false, // 缓存文件不要压缩
            }
          }
        ]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, '../src'),
      exclude: "node_modules", // 默认值
      cache: true,//开启缓存
      // 缓存目录
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 将public内资源赋值到dist中
    isProduction && new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../public'),
          to: path.resolve(__dirname, '../dist'),
          globOptions: {
            // 忽略index.html文件
            ignore: ["**/index.html"]
          }
        },
      ],
    }),
    // 提取css成单独文件
    isProduction && new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/[name].[contenthash:10].css",
      chunkFilename: "static/css/[name].chunk.[contenthash:10].css"
    }),

    new VueLoaderPlugin(),
    // cross-env定义的环境变量给打包工具使用
    // DefinePlugin定义的环境变量是给源代码使用的
    new DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false,
      __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
    }),

    // elementplus按需引入组件库
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver({
        importStyle: "sass",
      })],
    }),

  ].filter(Boolean),
  // 压缩的放这里
  optimization: {
    // 代码分割配置
    splitChunks: {
      chunks: "all", // 对所有模块都进行分割
      cacheGroups: {
        // vue、elementPlus 分开单独打包
        vue: {
          test: /[\\/]node_modules[\\/]vue(.*)?[\\/]/,
          name: "vue-chunk",
          priority: 40,
        },
        elementPlus: {
          test: /[\\/]node_modules[\\/]element-plus[\\/]/,
          name: "elementPlus-chunk",
          priority: 30,
        },
        libs: {
          test: /[\\/]node_modules[\\/]/,
          name: "libs-chunk",
          priority: 20,
        },
      },
    },
    // 将依赖关系单独一个文件，便于只更新改动的文件名
    runtimeChunk: {
      name: entrypoint => `runtime~${entrypoint.name}.js`,
    },
    minimize: isProduction,
    minimizer: [
      new CssMinimizerPlugin(), //压缩css
      new TerserPlugin(),
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminGenerate,
          options: {
            plugins: [
              ["gifsicle", { interlaced: true }],
              ["jpegtran", { progressive: true }],
              ["optipng", { optimizationLevel: 5 }],
              [
                "svgo",
                {
                  plugins: [
                    "preset-default",
                    "prefixIds",
                    {
                      name: "sortAttrs",
                      params: {
                        xmlnsOrder: "alphabetical",
                      },
                    },
                  ],
                },
              ],
            ],
          },
        },
      })
    ],
  },
  resolve: {
    // 自动补全文件扩展名
    extensions: ['.vue', '.js', '.json'],
    alias: {
      "@": path.resolve(__dirname, "../src")
    }
  },
  // 模式
  mode: isProduction ? "production" : "development",
  devtool: isProduction ? "source-map" : "cheap-module-source-map",
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3001", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
    hot: true, // 开启HMR功能，默认true（只能用于开发环境，生产环境不需要了）
    historyApiFallback: true, //前端访问报404时，显示index.html页面
  },
}
